package main

import (
	"image"
	"os/exec"
	"regexp"
	"strings"

	"code.google.com/p/jnj.plan9/draw"
	"code.google.com/p/jnj/graphics"
	"code.google.com/p/jnj/graphics/plan9"
	"code.google.com/p/jnj/graphics/text"
)

func domouse(mouse *draw.Mousectl) {
	// multiplex mouse, keyboard and clipboard events into tag and buf
	mchan := plan9.SetupMouseChan(mouse)
	kchan := plan9.SetupKeyboardChan(disp.InitKeyboard())

	pressed1, pressed2, pressed3 := false, false, false
	current := mainwin.edit
	for {
		select {
		case me := <-mchan:
			// don't set current when sweeping
			if me.Buttons != 1 || (me.Buttons == 1 && pressed1 == false) {
				current = getcurrent(me, current)
			}
			current.MouseChan <- me
			response := <-current.ClickChan
			switch me.Buttons {
			case 0:
				if pressed2 && response != nil {
					mainwin.edit.PushState()
					clickstring := current.StringAtAddress(*response)
					if f, ok := commands[clickstring]; ok {
						f()
					} else {
						fields := strings.Fields(clickstring)
						var args []string
						if len(fields) > 1 {
							args = fields[1:]
						}
						if len(fields) > 0 {
							out, err := exec.Command(fields[0], args...).CombinedOutput()
							s := string(out)
							if err != nil {
								s += err.Error()
							}
							//outbuf.LoadString(s)
						}
					}
				} else if pressed3 && response != nil {
					mainwin.edit.PushState()
					clickstring := current.StringAtAddress(*response)
					if clickstring == "" {
						continue
					}
					contents := mainwin.edit.Contents()
					re, err := regexp.Compile(clickstring)
					if err != nil {
						continue
					}

					var found bool
					find := func(startrow, startcol int) {
						for row, s := range contents[startrow:] {
							loc := re.FindStringIndex(s[startcol:])
							if loc != nil {
								found = true
								r := row + startrow
								left := image.Pt(loc[0]+startcol, r)
								right := image.Pt(loc[1]+startcol, r)
								next := mainwin.edit.NewAddress(left, right)
								mainwin.edit.Select(next)

								// warp the mouse
								disp.MoveTo(mainwin.edit.PointAtAddress(next))
								break
							}
							startcol = 0
						}
					}

					// start searching from the right edge of dot in the edit window
					find(mainwin.edit.Dot.Right.Y, mainwin.edit.Dot.Right.X)

					if found == false {
						// try again from the beginning
						find(0, 0)
					}

				}
				pressed1, pressed2, pressed3 = false, false, false

			// B1 (set focus)
			case 1:
				if pressed1 {
					break
				}
				mainwin.edit.PushState()
				pressed1 = true

			// B2 (execute)
			case 2:
				pressed2 = true

			// B3 (search)
			case 4:
				pressed3 = true
			}

		case r := <-kchan:
			current.KeyboardChan <- r
			if current == mainwin.edit {
				mainwin.dirty = true
				updatetag()
			}
		}
	}
}

func getcurrent(me *graphics.MouseEvent, old *text.Buffer) *text.Buffer {
	if me.In(mainwin.edit.Bounds()) {
		return mainwin.edit
	} else if me.In(mainwin.tag.Bounds()) {
		return mainwin.tag
		//} else if me.In(output.Bounds()) {
		//	return output
		//} else if me.In(outputtag.Bounds()) {
		//	return outputtag
	}
	return old
}
